package xj.util.gui;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.util.ArrayList;
import java.util.List;

public class DialogLayout 
  implements LayoutManager, JavaLookAndFeelConstants {

  public static final String LEFT = "Left";

  public static final String RIGHT = "Right";

  public static final String CENTER = "Center";

  public static final String ACTION = "ACTION";

  // last row policy
  public static final int NO_STRETCH = 0;

  public static final int STRETCH_ALL = 1;

  public static final int STRETCH_CENTER = 2;

  public DialogLayout() {
    this(NO_STRETCH);
  }

  public DialogLayout(int lastRowPolicy) {
    this.lastRowPolicy = lastRowPolicy;
  }

  public void addLayoutComponent(String name, Component comp) {
    if (comp != null) {
      if (name != null) {
	if (name.equals(LEFT)) {
	  leftColumn.add(comp);
	} else if (name.equals(RIGHT)) {
	  rightColumn.add(comp);
	} else if (name.equals(CENTER)) {
	  centerColumn.add(comp);
	} else {
	  actionRow.add(comp);
	}
      } else {
	actionRow.add(comp);
      }
    }
  }

  public void removeLayoutComponent(Component comp) {
    if (comp != null) {
      if (leftColumn.remove(comp) || 
	  centerColumn.remove(comp) || 
	  rightColumn.remove(comp) || 
	  actionRow.remove(comp)) {
	;
      }
    }
  }

  public void layoutContainer(Container parent) {
    int i;
    Component comp;
    Dimension compDim;

    int leftCount = leftColumn.size();
    int centerCount = centerColumn.size();
    int rightCount = rightColumn.size();
    int actionCount = actionRow.size();
    int leftColumnWidth = 0;
    for (i = 0; i < leftCount; i++) {
      comp = leftColumn.get(i);
      if (comp != null) {
	compDim = comp.getPreferredSize();
	if (compDim != null && compDim.width > leftColumnWidth) {
	  leftColumnWidth = compDim.width;
	}
      }
    }
    int centerColumnMinWidth = 0;
    for (i = 0; i < centerCount; i++) {
      comp = centerColumn.get(i);
      if (comp != null) {
	compDim = comp.getMinimumSize();
	if (compDim != null && compDim.width > centerColumnMinWidth) {
	  centerColumnMinWidth = compDim.width;
	}
      }
    }
    int rightColumnWidth = 0;
    for (i = 0; i < rightCount; i++) {
      comp = rightColumn.get(i);
      if (comp != null) {
	compDim = comp.getPreferredSize();
	if (compDim != null && compDim.width > rightColumnWidth) {
	  rightColumnWidth = compDim.width;
	}
      }
    }

    Dimension d = parent.getSize();
    int w = d.width;
    int h = d.height;
    Insets insets = parent.getInsets();
    if (insets != null) {
      w -= (insets.left + insets.right);
      h -= (insets.top + insets.bottom);
    }
    int centerColumnWidth = w - 2 * DIALOG_MARGIN;
    if (leftCount > 0) {
      centerColumnWidth -= (leftColumnWidth + DIALOG_LABEL_GAP);
    }
    if (rightCount > 0) {
      centerColumnWidth -= (rightColumnWidth + DIALOG_LABEL_GAP);
    }
    if (centerColumnWidth < centerColumnMinWidth) {
      centerColumnWidth = centerColumnMinWidth;
    }

    int actionRowHeight = 0;
    int actionRowWidth = 0;
    if (actionCount > 0) {
      for (i = 0; i < actionCount; i++) {
	comp = actionRow.get(i);
	if (comp != null) {
	  compDim = comp.getPreferredSize();
	  if (compDim != null) {
	    actionRowWidth += (compDim.width + DIALOG_ELEMENT_GAP);
	    if (compDim.height > actionRowHeight) {
	      actionRowHeight = compDim.height;
	    }
	  }
	}
      }
    }

    int bottom = d.height - DIALOG_MARGIN;
    if (actionRowHeight > 0) {
      bottom -= (actionRowHeight + DIALOG_FOOTER_SEP * 2);
    }
    int rowCount = Math.max(Math.max(leftCount, centerCount), rightCount);
    int x0 = DIALOG_MARGIN;
    int y = DIALOG_MARGIN;
    if (insets != null) {
      x0 += insets.left;
      y += insets.top;
      bottom -= insets.bottom;
    }
    int x = x0;

    if (debug) {
      System.out.println("d.width=" + d.width);
      System.out.println("d.height=" + d.height);
      System.out.println("leftColumnWidth=" + leftColumnWidth);
      System.out.println("centerColumnMinWidth=" + centerColumnMinWidth);
      System.out.println("centerColumnWidth=" + centerColumnWidth);
      System.out.println("rightColumnWidth=" + rightColumnWidth);
      System.out.println("actionRowHeight=" + actionRowHeight);
      System.out.println("bottom=" + bottom);
      System.out.println("y=" + y);
    }

    for (i = 0; i < rowCount; i++) {
      Component leftComp = (i < leftCount) ?  leftColumn.get(i) : null;
      Component centerComp = (i < centerCount) ?  centerColumn.get(i) : null;
      Component rightComp = (i < rightCount) ?  rightColumn.get(i) : null;
      Dimension leftDim = (leftComp != null) ? leftComp.getPreferredSize() : null;
      Dimension centerDim = (centerComp != null) ? centerComp.getPreferredSize() : null;
      Dimension rightDim = (rightComp != null) ? rightComp.getPreferredSize() : null;
      int rowHeight = 0;
      if (i == (rowCount - 1) && 
	  (lastRowPolicy == STRETCH_ALL || 
	   lastRowPolicy == STRETCH_CENTER)) {
	rowHeight = bottom - y;
      } else {
	if (leftDim != null && 
	    leftDim.height > rowHeight) {
	  rowHeight = leftDim.height;
	}
	if (centerDim != null && 
	    centerDim.height > rowHeight) {
	  rowHeight = centerDim.height;
	}
	if (rightDim != null && 
	    rightDim.height > rowHeight) {
	  rowHeight = rightDim.height;
	}
      }

      if (debug) {
	System.out.println("Layout row " + i + ": y=" + y);
	System.out.println("  leftDim.height=" + (leftDim != null ? leftDim.height : 0));
	System.out.println("  centerDim.height=" + (centerDim != null ? centerDim.height : 0));
	System.out.println("  rightDim.height=" + (rightDim != null ? rightDim.height : 0));
	System.out.println("  rowHeight=" + rowHeight);
      }

      x = x0;
      if (leftCount > 0) {
	if (leftComp != null) {
	  /*
	   * leftComp.setBounds(x, y + (rowHeight - leftDim.height) / 2,
	   * leftColumnWidth, leftDim.height);
	   */
	  if (i == (rowCount - 1) && lastRowPolicy == STRETCH_ALL) {
	    // (y + rowHeight) < bottom ) {
	    leftComp.setBounds(x, y, leftColumnWidth, bottom - y);
	  } else {
	    leftComp.setBounds(x, y, leftColumnWidth, rowHeight);
	  }
	}
	x += (leftColumnWidth + DIALOG_LABEL_GAP);
      }
      if (centerCount > 0) {
	if (centerComp != null) {
	  if (i == (rowCount - 1)
	      && (lastRowPolicy == STRETCH_ALL || lastRowPolicy == STRETCH_CENTER)) {
	    if (leftComp != null) { 
	      centerComp.setBounds(x, y, centerColumnWidth, bottom - y);
	    } else { 
	      int dw = leftColumnWidth + DIALOG_LABEL_GAP;
	      centerComp.setBounds(x - dw, y, 
				   centerColumnWidth + dw, bottom - y);
	    }
	  } else {
	    centerComp.setBounds(x, y + (rowHeight - centerDim.height) / 2,
				 centerColumnWidth, centerDim.height);
	  }
	}
	x += (centerColumnWidth + DIALOG_LABEL_GAP);
      }
      if (rightCount > 0) {
	if (rightComp != null) {
	  if (i == (rowCount - 1) && lastRowPolicy == STRETCH_ALL) {
	    // (y + rightDim.height) < bottom ) {
	    rightComp.setBounds(x, y, rightColumnWidth, bottom - y);
	  } else {
	    rightComp.setBounds(x, y + (rowHeight - rightDim.height) / 2,
				rightColumnWidth, rightDim.height);
	  }
	}
      }
      y += (rowHeight + DIALOG_ELEMENT_GAP);
    }

    if (actionCount > 0) {
      y = y - DIALOG_ELEMENT_GAP + DIALOG_FOOTER_SEP;
      if (actionRowWidth > 0) {
	x = w - actionRowWidth - DIALOG_ELEMENT_GAP + x0;
	if (x < x0) {
	  x = x0;
	}
	for (i = 0; i < actionCount; i++) {
	  comp = actionRow.get(i);
	  if (comp != null) {
	    compDim = comp.getPreferredSize();
	    comp.setBounds(x, y, compDim.width, compDim.height);
	    x += (compDim.width + DIALOG_ELEMENT_GAP);
	  }
	}
      }
    }
  }

  public Dimension minimumLayoutSize(Container parent) {
    if (dim != null) {
      return dim;
    } else {
      return preferredLayoutSize(parent);
    }
  }

  public Dimension preferredLayoutSize(Container parent) {
    if (dim == null) {

      int i;
      Component comp;
      Dimension compDim;
      int width = 0;
      int leftCount = leftColumn.size();
      int centerCount = centerColumn.size();
      int rightCount = rightColumn.size();
      int actionCount = actionRow.size();
      int leftColumnWidth = 0;
      for (i = 0; i < leftCount; i++) {
	comp = leftColumn.get(i);
	if (comp != null) {
	  compDim = comp.getPreferredSize();
	  if (compDim != null && compDim.width > leftColumnWidth) {
	    leftColumnWidth = compDim.width;
	  }
	}
      }
      int centerColumnWidth = 0;
      for (i = 0; i < centerCount; i++) {
	comp = centerColumn.get(i);
	if (comp != null) {
	  compDim = comp.getPreferredSize();
	  if (compDim != null && compDim.width > centerColumnWidth) {
	    centerColumnWidth = compDim.width;
	  }
	}
      }
      int rightColumnWidth = 0;
      for (i = 0; i < rightCount; i++) {
	comp = rightColumn.get(i);
	if (comp != null) {
	  compDim = comp.getPreferredSize();
	  if (compDim != null && compDim.width > rightColumnWidth) {
	    rightColumnWidth = compDim.width;
	  }
	}
      }

      int rowCount = Math.max(Math.max(leftCount, centerCount), rightCount);
      int y = DIALOG_MARGIN;
      int x = DIALOG_MARGIN;
      for (i = 0; i < rowCount; i++) {
	Component leftComp = (i < leftCount) ?  leftColumn.get(i) : null;
	Component centerComp = (i < centerCount) ?  centerColumn.get(i) : null;
	Component rightComp = (i < rightCount) ?  rightColumn.get(i) : null;
	Dimension leftDim = (leftComp != null) ? leftComp.getPreferredSize() : null;
	Dimension centerDim = (centerComp != null) ? centerComp.getPreferredSize() : null;
	Dimension rightDim = (rightComp != null) ? rightComp.getPreferredSize() : null;
	int rowHeight = 0;
	if (leftDim != null && leftDim.height > rowHeight) {
	  rowHeight = leftDim.height;
	}
	if (centerDim != null && centerDim.height > rowHeight) {
	  rowHeight = centerDim.height;
	}
	if (rightDim != null && rightDim.height > rowHeight) {
	  rowHeight = rightDim.height;
	}

	y += (rowHeight + DIALOG_ELEMENT_GAP);
      }

      x = DIALOG_MARGIN;
      if (leftCount > 0) {
	x += (leftColumnWidth + DIALOG_LABEL_GAP);
      }
      if (centerCount > 0) {
	x += (centerColumnWidth + DIALOG_LABEL_GAP);
      }
      if (rightCount > 0) {
	x += (rightColumnWidth + DIALOG_LABEL_GAP);
      }
      width = x - DIALOG_LABEL_GAP + DIALOG_MARGIN;

      int actionRowHeight = 0;
      int actionRowWidth = 0;
      if (actionCount > 0) {
	for (i = 0; i < actionCount; i++) {
	  comp = actionRow.get(i);
	  if (comp != null) {
	    compDim = comp.getPreferredSize();
	    if (compDim != null) {
	      actionRowWidth += (compDim.width + DIALOG_ELEMENT_GAP);
	      if (compDim.height > actionRowHeight) {
		actionRowHeight = compDim.height;
	      }
	    }
	  }
	}
	y = y - DIALOG_ELEMENT_GAP + DIALOG_FOOTER_SEP;
	if (actionRowWidth > 0) {
	  y += (actionRowHeight + DIALOG_FOOTER_SEP);
	}
      }

      dim = new Dimension(Math.max(actionRowWidth - DIALOG_ELEMENT_GAP + 2 * DIALOG_MARGIN, width), y);

      Insets insets = parent.getInsets();
      if (insets != null) {
	dim.width += (insets.left + insets.right);
	dim.height += (insets.top + insets.bottom);
      }
    }
    return dim;
  }

  protected List<Component> leftColumn = new ArrayList<Component>(8);

  protected List<Component> centerColumn = new ArrayList<Component>(8);

  protected List<Component> rightColumn = new ArrayList<Component>(8);

  protected List<Component> actionRow = new ArrayList<Component>(8);

  protected int lastRowPolicy = 0;

  protected Dimension dim = null;

  static protected final boolean debug = false;

}
